package frame

import (
	"fmt"

	"gitee.com/go-mao/mao/libs/try"
	"xorm.io/xorm"
)

// orm结构体集成该属性可以进行相关操作
type Model struct {
	obj           ModelInterface //model对象
	usePrimarykey bool           //使用默认主键查询
	omit          []string
	cols          []string
	must          []string
	data          any
	cache         bool
	sess          *xorm.Session
	tableName     string
}

func (this *Model) init(sess *xorm.Session, obj ModelInterface) {
	this.sess = sess
	this.obj = obj
	this.reset()
}

// 初始化操作
func (this *Model) reset() {
	this.omit = make([]string, 0)
	this.cols = make([]string, 0)
	this.must = make([]string, 0)
	this.usePrimarykey = true
	return
}

// 设置表名
func (this *Model) SetTableName(tableName string) {
	this.tableName = tableName
}

// 表名
func (this *Model) TableName() string {
	return this.tableName
}

// 表别名
func (this *Model) Alias(alias string) string {
	return fmt.Sprintf("`%s` as `%s`", this.obj.TableName(), alias)
}

// 必须有的字段，比如age=0会强制写入数据库
func (this *Model) Must(cols ...string) *Model {
	this.must = append(this.must, cols...)
	return this
}

// 忽略添加修改的字段
func (this *Model) Omit(cols ...string) *Model {
	this.omit = append(this.omit, cols...)
	return this
}

// 指定添加修改的字段
func (this *Model) Cols(cols ...string) *Model {
	this.cols = append(this.cols, cols...)
	return this
}

// 使用条件查询
func (this *Model) Where(query string, args ...any) *Model {
	this.sess.Where(query, args...)
	this.usePrimarykey = false
	return this
}

// 对data进行增删改查，优先于this.object
func (this *Model) SetData(data any) *Model {
	this.data = data
	return this
}

// 根据指定字段获取对象
func (this *Model) Match(column string, data any) *Model {
	this.sess.And("`"+column+"`=?", data)
	this.usePrimarykey = false
	return this
}

// 是否存在
func (this *Model) Exists() bool {
	sx := this.sess.Table(this.obj).Limit(1)
	b, err := sx.NoAutoCondition().Exist(this.entity())
	CheckSqlError(err)
	return b
}

// 查询数据信息（根据ID）
func (this *Model) Get() bool {
	sx := this.sess.Table(this.obj)
	b, err := sx.NoAutoCondition().Get(this.entity())
	CheckSqlError(err)
	return b
}

// 添加数据
func (this *Model) Create() bool {
	sx := this.sess.Table(this.obj)
	l, err := sx.InsertOne(this.entity())
	CheckSqlError(err)
	return l == 1
}

// 修改数据
func (this *Model) Update() bool {
	sx := this.sess.Limit(1)
	l, err := sx.Update(this.entity())
	CheckSqlError(err)
	return l == 1
}

// 删除数据（只针对主键id删除）
func (this *Model) Delete() bool {
	sx := this.sess.Limit(1)
	l, err := sx.NoAutoCondition().Delete(this.entity())
	CheckSqlError(err)
	return l == 1
}

// 获取对象，并进行预处理
func (this *Model) entity() any {
	var obj any = this.obj
	if this.usePrimarykey {
		this.sess.ID(this.obj.PrimaryKey())
	}
	if len(this.cols) > 0 {
		this.sess.Cols(this.cols...)
	}
	if len(this.omit) > 0 {
		this.sess.Omit(this.omit...)
	}
	if len(this.must) > 0 {
		this.sess.MustCols(this.must...)
	}
	if this.data != nil {
		obj = this.data
	}
	this.reset()
	return obj
}

func CheckSqlError(err error) {
	if err == nil {
		return
	}
	try.Throw(CODE_SQL, err.Error())
}
